# -*- coding: utf-8 -*-
# vim: set noet ts=4:
#
# scim-python
#
# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
#
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA  02111-1307  USA
#
# $Id: $
#
import scim
from scim import KeyCode
from scim import KeyMask
import os
import traceback
import enchant
import locale
from time import strftime

from gettext import dgettext
_ = lambda (a) : dgettext ("scim-python", a)
N_ = lambda (a) : a

IMEngine = scim.IMEngine
IMEngineFactory = scim.IMEngineFactory

class Engine (IMEngine):
	def __init__ (self, factory, config, db, encoding, id):
		IMEngine.__init__ (self, factory, config, encoding, id)
		self._config = config
		self._lookup_table = scim.LookupTable (9)
		self._preedit_string = u""
		self._db = db
		self._cursor = 0
		self._candidates = []
		self._always_show_candidates = config.read ("/IMEngine/Python/AlwaysShowCandidates", False)
		self._commit_space = config.read ("/IMEngine/Python/CommitSpace", True)

	def get_candidates (self, check = True):
		candidates = []
		if self._preedit_string == u"date":
			candidates.append (u"date")
			candidates.append (unicode (strftime ("%x")))
		elif self._preedit_string == u"time":
			candidates.append (u"time")
			candidates.append (unicode (strftime ("%X")))
			candidates.append (unicode (strftime ("%c")))
			
		if self._db.check (self._preedit_string) and check:
			self._candidates = candidates + []
		else:
			words = map (unicode, self._db.suggest(self._preedit_string))
			lower = self._preedit_string.islower ()
			self._candidates = candidates + [c for c in words if c.islower() == lower]
	
	def update (self):
		if not self._candidates:
			self.hide_lookup_table ()

		self._lookup_table.clear ()
		
		for can in self._candidates:
			self._lookup_table.append_candidate (can)
		self.update_lookup_table (self._lookup_table)
		
		attrs = []
		if self._candidates:
			attrs.append (scim.Attribute (0, len (self._preedit_string), scim.ATTR_FOREGROUND, 0x00ff0000))
			attrs.append (scim.Attribute (0, len (self._preedit_string), scim.ATTR_DECORATE, scim.ATTR_DECORATE_UNDERLINE))
		self.update_preedit_string (self._preedit_string, attrs)
		self.update_preedit_caret (self._cursor)
		if self._preedit_string:	
			self.show_preedit_string ()
		else:
			self.hide_preedit_string ()
		
		if self._candidates:
			self.show_lookup_table ()

	def process_key_event (self, key):
		if key.mask & KeyMask.ReleaseMask: # Ignore release event
			return False
		if key.mask & KeyMask.ControlMask:
			return False
		if key.mask & KeyMask.CapsLockMask:
			return False
		
		if (key.code >= KeyCode.KEY_a and key.code <= KeyCode.KEY_z) or \
			(key.code >= KeyCode.KEY_A and key.code <= KeyCode.KEY_Z) or \
			(key.code == KeyCode.KEY_apostrophe and self._cursor != 0):
			ls = list (self._preedit_string)
			ls.insert (self._cursor, unichr (key.code))
			self._preedit_string = u"".join (ls)
			self._cursor += 1
			self.get_candidates (not self._always_show_candidates)
			self.update ()
			return True
		elif key.code == KeyCode.KEY_Page_Up:
			if not self._preedit_string:
				return False
			if self._candidates:
				self.lookup_table_page_up ()
			else:
				self.get_candidates (False)
				self.update ()
			return True
		elif key.code == KeyCode.KEY_Page_Down:
			if not self._preedit_string:
				return False
			if self._candidates:
				self.lookup_table_page_down ()
			else:
				self.get_candidates (False)
				self.update ()
			return True
		elif key.code == KeyCode.KEY_Left:
			if self._cursor > 0:
				self._cursor -= 1
				self.update_preedit_caret (self._cursor)
			if self._preedit_string:
				return True
			return False
		elif key.code == KeyCode.KEY_Right:
			if self._cursor < len (self._preedit_string):
				self._cursor += 1
				self.update_preedit_caret (self._cursor)
			if self._preedit_string:
				return True
			return False
		elif key.code >= KeyCode.KEY_1 and key.code <= KeyCode.KEY_9:
			i = key.code - KeyCode.KEY_1
			if i >= len (self._candidates):
				self.commit_string ()
				return False
			if self._commit_space:
				self.commit_string (self._candidates[i] + u" ")
			else:
				self.commit_string (self._candidates[i])

			return True	
		elif key.code == KeyCode.KEY_Return:
			if self._preedit_string:
				self.commit_string ()
				return True
			return False		
		elif key.code in (KeyCode.KEY_KP_Space, KeyCode.KEY_space):
			if self._candidates:
				self.commit_string (self._candidates[0])
			elif self._preedit_string:
				self.commit_string ()
			else:
				return False			
			if self._commit_space:
				return False
			else:
				return True
		elif key.code == KeyCode.KEY_BackSpace:
			if self._preedit_string and self._cursor > 0:
				ls = list (self._preedit_string)
				del ls[self._cursor - 1]
				self._preedit_string = u"".join (ls)
				self._cursor -= 1
				self.get_candidates ()
				self.update ()
				return True
			return False
		
		if self._preedit_string:
			self.commit_string ()
		return False
			
	def commit_string (self, string = None):
		if string == None:
			string = self._preedit_string
		self._preedit_string = u""
		self._candidates = []
		self._cursor = 0
		IMEngine.commit_string (self, string)
		self.update ()

	def move_preedit_caret (self, pos):
		IMEngine.move_preedit_caret (self, pos)
	
	def select_candidate (self, index):
		IMEngine.select_candidate (self, index)

	def update_lookup_table_page_size (self, page_size):
		IMEngine.update_lookup_table_page_size (self, page_size)

	def lookup_table_page_up (self):
		if self._lookup_table.page_up ():
			self.update_lookup_table (self._lookup_table)
			return True
		IMEngine.lookup_table_page_up (self)
		return False

	def lookup_table_page_down (self):
		if self._lookup_table.page_down ():
			self.update_lookup_table (self._lookup_table)
			return True
		IMEngine.lookup_table_page_down (self)
		return False

	def reset (self):
		self._preedit_string = u""
		self._candidates = []
		self._cursor = 0
		self.update ()
		IMEngine.reset (self)

	def focus_in (self):
		IMEngine.focus_in (self)
		self.update ()
	
	def focus_out (self):
		self.reset ()
		IMEngine.focus_out (self)

	def trigger_property (self, property):
		IMEngine.trigger_property (self, property)

	def process_helper_event (self, helper_uuid, trans):
		IMEngine.process_helper_event (self, helper_uuid, trans)

	def update_client_capabilities (self, cap):
		IMEngine.update_client_capabilities (self, cap)

	def reload_config (self, config):
		self._always_show_candidates = config.read ("/IMEngine/Python/AlwaysShowCandidates", False)
		self._commit_space = config.read ("/IMEngine/Python/CommitSpace", True)


class Factory (IMEngineFactory):
	def __init__ (self, config):
		IMEngineFactory.__init__ (self, config)
		self._config	= config
		self.name 		= _(u"English Writer")
		self.uuid 		= "7fb43ae9-0d72-4d7a-b255-f437ce28d599"
		self.authors	= u"Huang Peng <shawn.p.huang@gmail.com>"
		self.icon_file 	= "/usr/share/scim/icons/scim-python.png"
		self.credits 	= _(u"")
		self.help		= _(u"Help For English")
		self.set_languages ("en")
		self._dict = enchant.Dict ("en")
		locale.setlocale (locale.LC_ALL, "en_US.UTF-8")

	def create_instance (self, encoding, id):
		engine =  Engine (self, self._config, self._dict, encoding, id)
		return engine

	def reload_config (self, config):
		pass		
